package com.tianji.learning.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.api.client.course.CatalogueClient;
import com.tianji.api.client.course.CourseClient;
import com.tianji.api.dto.IdAndNumDTO;
import com.tianji.api.dto.course.CataSimpleInfoDTO;
import com.tianji.api.dto.course.CourseFullInfoDTO;
import com.tianji.api.dto.course.CourseSimpleInfoDTO;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.domain.query.PageQuery;
import com.tianji.common.exceptions.BadRequestException;
import com.tianji.common.exceptions.ForbiddenException;
import com.tianji.common.utils.*;
import com.tianji.learning.domain.dto.LearningPlanDTO;
import com.tianji.learning.domain.po.LearningLesson;
import com.tianji.learning.domain.po.LearningRecord;
import com.tianji.learning.domain.vo.LearningLessonVO;
import com.tianji.learning.domain.vo.LearningPlanPageVO;
import com.tianji.learning.domain.vo.LearningPlanVO;
import com.tianji.learning.enums.LessonStatus;
import com.tianji.learning.enums.PlanStatus;
import com.tianji.learning.mapper.LearningLessonMapper;
import com.tianji.learning.mapper.LearningRecordMapper;
import com.tianji.learning.service.ILearningLessonService;
import com.tianji.learning.service.ILearningRecordService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>
 * 学生课程表 服务实现类
 * </p>
 *
 * @author lyh
 * @since 2024-12-03
 */
@Service
@RequiredArgsConstructor
public class LearningLessonServiceImpl extends ServiceImpl<LearningLessonMapper, LearningLesson> implements ILearningLessonService {
    private final CourseClient courseClient;
    private final CatalogueClient catalogueClient;

    @Autowired
    @Lazy
    private ILearningRecordService learningRecordService;
    @Override
    public void savelession(Long userId, List<Long> courseIds) {
        //课程是否为空
        if(CollectionUtil.isEmpty(courseIds)){
            return;
        }
        //查询已购买的课程，处理，得到购买课程的id
        List<Long> list = this.lambdaQuery().eq(LearningLesson::getUserId, userId).list().stream().map(learningLesson -> {
            return learningLesson.getCourseId();
        }).collect(Collectors.toList());
        //去掉已购买的课程·
        if(CollectionUtil.isNotEmpty(list)){
            courseIds.removeAll(list);
        }
        if(CollectionUtil.isEmpty(courseIds)){
            return;
        }
        //封装课程属性，批量添加
        List<CourseSimpleInfoDTO> simpleInfoList = courseClient.getSimpleInfoList(courseIds);
        if((CollectionUtil.isNotEmpty(simpleInfoList))){
            List<LearningLesson> lessons = simpleInfoList.stream().map(courseSimpleInfoDTO -> {
                LearningLesson lesson = new LearningLesson();
                //设置属性
                //userid
                lesson.setUserId(userId);
                //courseid
                lesson.setCourseId(courseSimpleInfoDTO.getId());
                //过期时间
                Integer validDuration = courseSimpleInfoDTO.getValidDuration();
                lesson.setExpireTime(LocalDateTime.now().plusMonths(validDuration));
                return lesson;
            }).collect(Collectors.toList());
            saveBatch(lessons);
        }
    }
   //查询我的课表
    @Override
    public PageDTO<LearningLessonVO> queryMyLessons(PageQuery query) {
        //获取当前登录对象的id
        Long userId = UserContext.getUser();
        //分页查询条件
        Page<LearningLesson> page = lambdaQuery()
                .eq(LearningLesson::getUserId, userId)
                .page(query.toMpPage("latest_learn_time", false));
        List<LearningLesson> records = page.getRecords();
        //如果为空，返回空对象
        if(CollectionUtil.isEmpty(records)){
            return PageDTO.empty(page);
        }
        //获取集合中的courseid集合
        Set<Long> list = records.stream().map(record -> {
            return record.getCourseId();
        }).collect(Collectors.toSet());
        //根据courseids查询course集合
        List<CourseSimpleInfoDTO> infoList = courseClient.getSimpleInfoList(list);
        //将集合转为map
        Map<Long, CourseSimpleInfoDTO> map = infoList.stream().collect(Collectors.toMap(CourseSimpleInfoDTO::getId, c -> c));
        ArrayList<LearningLessonVO> learningLessonVOS = new ArrayList<>(records.size());
        for (LearningLesson record : records) {
            LearningLessonVO learningLessonVO = BeanUtils.copyBean(record, LearningLessonVO.class);
            //根据课程id获取课程对象
            CourseSimpleInfoDTO courseSimpleInfoDTO = map.get(record.getCourseId());
            //封装learningLessonVO缺少的属性
            learningLessonVO.setCourseName(courseSimpleInfoDTO.getName());
            learningLessonVO.setCourseCoverUrl(courseSimpleInfoDTO.getCoverUrl());
            learningLessonVO.setSections(courseSimpleInfoDTO.getSectionNum());
            learningLessonVOS.add(learningLessonVO);
        }
        return PageDTO.of(page,learningLessonVOS);
    }

    @Override
    public LearningLessonVO queryMyCurrentLesson() {
        //查询当前登录的用户id
        Long userId = UserContext.getUser();
        if(userId==null){
            throw new ForbiddenException("没有登录");
        }
        //查询最后学习的课程
        LearningLesson learningLesson = this.lambdaQuery().eq(LearningLesson::getUserId, userId)
                .eq(LearningLesson::getStatus, LessonStatus.LEARNING.getValue())
                .orderByDesc(LearningLesson::getLatestLearnTime)
                .last("limit 1").one();
        //判断learningLesson是否为空
        if(ObjectUtils.isEmpty(learningLesson)) {
            //为空，返回null
            return null;
        }
            LearningLessonVO learningLessonVO = BeanUtils.copyBean(learningLesson, LearningLessonVO.class);
            //封装缺少的属性
            CourseFullInfoDTO courseInfoById = courseClient.getCourseInfoById(learningLesson.getCourseId(), false, false);
            if (ObjectUtils.isEmpty(courseInfoById)) {
                throw new BadRequestException("课程已不存在");
            }
            learningLessonVO.setSections(courseInfoById.getSectionNum());
            learningLessonVO.setCourseName(courseInfoById.getName());
            learningLessonVO.setCourseCoverUrl(courseInfoById.getCoverUrl());
            //courseAmount 当前用户的功课数
            Integer count = this.lambdaQuery().eq(LearningLesson::getUserId, userId).count();
            learningLessonVO.setCourseAmount(count);
            //将最后学习的小节id封装为集合
            ArrayList<Long> list = CollUtils.toList(learningLesson.getLatestSectionId());
            //查询小节信息
            List<CataSimpleInfoDTO> cataSimpleInfoDTOS = catalogueClient.batchQueryCatalogue(list);
            if(CollUtils.isNotEmpty(cataSimpleInfoDTOS)){
                CataSimpleInfoDTO cataSimpleInfoDTO = cataSimpleInfoDTOS.get(0);
                //latestSectionName   最后学习的章节名
                learningLessonVO.setLatestSectionName(cataSimpleInfoDTO.getName());
                //latestSectionIndex  最后学习的章节数
                learningLessonVO.setLatestSectionIndex(cataSimpleInfoDTO.getCIndex());
            }
          return learningLessonVO;
    }

    /**
     * 删除失效或者退款的课程
     * @param userId
     * @param courseIds
     */
    @Override
    public void deletelession(Long userId, List<Long> courseIds) {
        if(CollUtils.isEmpty(courseIds)){
            throw new BadRequestException("没有课程id");
        }
        if(userId!=null){
            //用户退款后触发课表自动删除
            LambdaQueryWrapper<LearningLesson> wrapper = Wrappers.<LearningLesson>lambdaQuery().eq(LearningLesson::getUserId, userId).eq(LearningLesson::getCourseId, courseIds.get(0));
            this.remove(wrapper);

        }else {
            //用户直接删除已失效的课程
            Long userId1 = UserContext.getUser();
            LambdaQueryWrapper<LearningLesson> wrapper = Wrappers.<LearningLesson>lambdaQuery().eq(LearningLesson::getUserId, userId1).eq(LearningLesson::getCourseId, courseIds.get(0));
            this.remove(wrapper);
        }
    }

    @Override
    public Long isLessonValid(Long courseId) {
        Long userId = UserContext.getUser();
        LearningLesson learningLesson = lambdaQuery().eq(LearningLesson::getUserId, userId).eq(LearningLesson::getCourseId, courseId).one();
        //用户课表中是否有该课程
        if(learningLesson==null){
            return null;
        }
        //课程状态是否是有效的状态（未过期）
        if(learningLesson.getStatus()==LessonStatus.EXPIRED){
            return null;
        }
        return learningLesson.getCourseId();
    }

    @Override
    public LearningLessonVO getByCourseIdAndUserId(Long courseId) {
        Long userId = UserContext.getUser();
        LearningLesson learningLesson = lambdaQuery().eq(LearningLesson::getUserId, userId).eq(LearningLesson::getCourseId, courseId).one();
        //判断learningLesson是否为空
        if(ObjectUtils.isEmpty(learningLesson)) {
            //为空，返回null
            return null;
        }
        LearningLessonVO lessonVO = BeanUtils.toBean(learningLesson, LearningLessonVO.class);
        return lessonVO;
    }

    @Override
    public Integer countLearningLessonByCourse(Long courseId) {
        Integer count = lambdaQuery().eq(LearningLesson::getCourseId, courseId).eq(LearningLesson::getStatus, LessonStatus.LEARNING).count();
        if(count==null){
            return 0;
        }
        return count;
    }

    @Override
    public void lessonPlan(LearningPlanDTO vo) {
        if(vo.getCourseId()==null||vo.getFreq()==null){
            throw new BadRequestException("参数不能为空");
        }
        LearningLesson lesson = lambdaQuery().eq(LearningLesson::getCourseId, vo.getCourseId()).eq(LearningLesson::getUserId, UserContext.getUser()).one();
        if(ObjectUtils.isEmpty(lesson)){
            throw new ForbiddenException("课程不存在");
        }
        this.lambdaUpdate().eq(LearningLesson::getId,lesson.getId()).set(LearningLesson::getWeekFreq,vo.getFreq()).set(LearningLesson::getPlanStatus, PlanStatus.PLAN_RUNNING).update();
    }
    @Autowired
    private LearningRecordMapper recordMapper;

    @Override
    public LearningPlanPageVO getMyPlan(PageQuery pageQuery) {
        LearningPlanPageVO vo = new LearningPlanPageVO();
        Long userId = UserContext.getUser();
        //获取一周开始的时间
        LocalDateTime begin = DateUtils.getWeekBeginTime(LocalDate.now());
        //获取一周结束的时间
        LocalDateTime end = DateUtils.getWeekEndTime(LocalDate.now());
        //select count(*) from learning_recores where user_id=? and finish_time between ? and ?
        Integer count = learningRecordService.lambdaQuery()
                .eq(LearningRecord::getUserId, userId)
                .between(LearningRecord::getFinishTime, begin, end)
                .count();
        vo.setWeekFinished(count);//本周完成的计划数量
        //select sum(week_freq) from learning_lesson where user_id=? and plan_status=1
       Integer total=getBaseMapper().countWeekTotalPlan(userId,PlanStatus.PLAN_RUNNING);
        vo.setWeekTotalPlan(total);//总的计划学习数量
        //vo.setWeekPoints();//本周积分值
        Page<LearningLesson> page = this.lambdaQuery()
                .eq(LearningLesson::getUserId, userId)
                .in(LearningLesson::getStatus, LessonStatus.LEARNING, LessonStatus.FINISHED)
                .page(pageQuery.toMpPageDefaultSortByCreateTimeDesc());
        vo.setPages(page.getPages());
        vo.setTotal(page.getTotal());
        List<LearningLesson> records = page.getRecords();
        if(CollectionUtils.isEmpty(records)){
            return vo;
        }
        Set<Long> set = records.stream().map(record -> {
            return record.getCourseId();
        }).collect(Collectors.toSet());
        List<CourseSimpleInfoDTO> infoList = courseClient.getSimpleInfoList(set);
        Map<Long, CourseSimpleInfoDTO> map = infoList.stream().collect(Collectors.toMap(CourseSimpleInfoDTO::getId, c -> c));
        List<IdAndNumDTO> idAndNumDTOS=recordMapper.countFinishSectionGROUPByLesson(userId,begin,end);
        Map<Long, Integer> map1 = IdAndNumDTO.toMap(idAndNumDTOS);
        List<LearningPlanVO> list=new ArrayList<>();
        for (LearningLesson record : records) {
            LearningPlanVO planVO = BeanUtils.copyBean(record, LearningPlanVO.class);
            CourseSimpleInfoDTO dto = map.getOrDefault(planVO.getCourseId(), new CourseSimpleInfoDTO());
            planVO.setSections(dto.getSectionNum());
            planVO.setCourseName(dto.getName());
            Integer integer = map1.getOrDefault(record.getId(), 0);
            planVO.setWeekLearnedSections(integer);
            list.add(planVO);
        }
        vo.setList(list);
        return vo;
    }
}
